package utils;

import org.apache.log4j.Logger;
import vo.CmdResult;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @author：xingquanxiang createTime:2020/4/28 11:00
 * description:
 */
public class VideoCutUtil {
    private final static String ffmpeg = "D:\\Application\\ffmpegF\\bin\\ffmpeg.exe";
    private static Logger logger = Logger.getLogger(VideoCutUtil.class);

    /**
     * 剪辑视频
     *
     * @param resource      资源文件
     * @param destDirectory 输出目录
     * @param timeLength    视频时长
     */
    public static void cutVideo(File resource, File destDirectory, long timeLength) {
        ArrayList<Long> timeList = getTimeList(timeLength);
        try {
            for (int i = 0; i < timeList.size()-1; i++) {

                List<String> commands = new ArrayList<String>();
                // String cmd = "D:\\Application\\ffmpeg\\bin\\ffmpeg.exe -i K:\\A\\石膏体\\单个塑造\\多面体\\MVI_0340.MP4  -ss  00:08:00  -t  00:08:22  -acodec copy -vcodec copy K:\\A\\石膏体\\单个塑造\\多面体\\MVI_0340\\MVI_0340_2.MP4";
                commands.add(ffmpeg);
                commands.add("-i");
                commands.add(resource.getAbsolutePath());
                commands.add("-ss");
                String beginTime = parseTimeToString(timeList.get(i));
                commands.add(beginTime);
                commands.add("-t");
                if (i==timeList.size()-2){
                    commands.add(parseTimeToString(timeList.get(i+1)));
                }else{
                    commands.add("00:15:00");
                }
                commands.add("-acodec");
                commands.add("copy");
                commands.add("-vcodec");
                commands.add("copy");
                String resourceName = resource.getName();
                String prefix = resourceName.substring(0, resourceName.indexOf('.'));
                String suffix = resourceName.substring(resourceName.indexOf('.'));
                commands.add(destDirectory.getAbsolutePath() + "\\" + prefix + "_" + (i + 1) + suffix);
                commands.add("-y");
                logger.info("---");
                StringBuilder cmd = new StringBuilder();
                for (String command : commands) {
                    cmd.append(command);
                    cmd.append(" ");
                }
                logger.info(cmd.toString());
                logger.info("---");
                CmdResult cmdResult = runCommand(commands);
                logger.info("cmdResult.isSuccess:"+cmdResult.isSuccess());
                logger.info("===========================");
            }

        } catch (Exception e) {
            e.printStackTrace();
            logger.info("报错："+e.getMessage());
        }
    }

    /**
     *
     * @param headVideo  片头视频 MP4转ts格式
     * @param resource  资源文件 MP4转ts格式
     * @param destFile  输出文件 MP4格式
     */
    public static void spliceVideo(File headVideo, File resource, File destFile){
        List<String> commands = new ArrayList<String>();
        // String spliceCmd ="ffmpeg -i 'concat:G:\\老鹰\\head.ts|G:\\老鹰\\mp4\\单个草堆.ts' -c copy -f mp4 G:\\老鹰\\mp4\\合成\\单个草堆.mp4";
        commands.add(ffmpeg);
        commands.add("-i");
        commands.add("\"concat:"+headVideo.getAbsolutePath()+"|"+resource.getAbsolutePath()+"\"");
        commands.add("-c");
        commands.add("copy");
        commands.add("-f");
        commands.add("mp4");
        commands.add("\""+destFile.getAbsolutePath()+"\"");
        commands.add("-y");
        logger.info("---");
        StringBuilder cmd = new StringBuilder();
        for (String command : commands) {
            cmd.append(command);
            cmd.append(" ");
        }
        logger.info(cmd.toString());
        logger.info("---");
        CmdResult cmdResult = runCommand(commands);
        logger.info("cmdResult.isSuccess:"+cmdResult.isSuccess());
        logger.info("===========================");
    }

    /**
     * 解码时评
     * @param resource  源视频
     * @param destFilePath  输出文件路径 后缀 .ts
     * @return
     */
    public static File decodingVideo(File resource, String destFilePath){
        File destFile = new File(destFilePath);
        if (destFile.exists()){
            logger.info("源视频解码已存在:" + destFilePath);
            return destFile;
        }
        List<String> commands = new ArrayList<String>();
        // String spliceCmd ="ffmpeg -i 'G:\\老鹰\\head.mp4' -c copy -f mpegts 'G:\\老鹰\\head.ts'";
        commands.add(ffmpeg);
        commands.add("-i");
        commands.add("\""+resource.getAbsolutePath()+"\"");
        commands.add("-c");
        commands.add("copy");
        commands.add("-f");
        commands.add("mpegts");
        commands.add("\""+destFilePath+"\"");
        commands.add("-y");
        logger.info("---");
        StringBuilder cmd = new StringBuilder();
        for (String command : commands) {
            cmd.append(command);
            cmd.append(" ");
        }
        logger.info(cmd.toString());
        logger.info("---");
        CmdResult cmdResult = runCommand(commands);
        logger.info("cmdResult.isSuccess:"+cmdResult.isSuccess());
        logger.info("===========================");
        if (!cmdResult.isSuccess()){
            logger.info("源视频解码失败:"+resource.getAbsolutePath());
        }
        return destFile;

    }
    /**
     * 获取时间节点
     * @param timeLength 集合最后一位为剩余时长
     * @return
     */
    private static ArrayList<Long> getTimeList(long timeLength) {
        ArrayList<Long> times = new ArrayList<>();
        long count = 0;
        long laveTime = 0;
        while (timeLength > 1000 * 60 * 30) {
            timeLength -= 1000 * 60 * 15;
            times.add(count * 1000 * 60 * 15);
            count++;
        }
        times.add(count * 1000 * 60 * 15);
        times.add(timeLength);

        return times;
    }

    /**
     * 执行命令
     * @param command
     * @return
     */
    private static synchronized CmdResult runCommand(List<String> command) {
        CmdResult cmdResult = new CmdResult(false, "");
        ProcessBuilder builder = new ProcessBuilder(command);
        builder.redirectErrorStream(true);
        try {
            Process process = builder.start();
            final StringBuilder stringBuilder = new StringBuilder();
            final InputStream inputStream = process.getInputStream();
            new Thread(new Runnable() {//启动新线程为异步读取缓冲器，防止线程阻塞

                @Override
                public void run() {
                    BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
                    String line;
                    try {
                        while ((line = reader.readLine()) != null) {
                            stringBuilder.append(line);
//                          mListener.isLoading(true);
                        }
//                        mListener.isLoading(false);
                        reader.close();
                    } catch (IOException e) {
                        e.printStackTrace();

                    }
                }
            }).start();
            process.waitFor();
            cmdResult.setSuccess(true);
            cmdResult.setMsg(stringBuilder.toString());
        } catch (Exception e) {
            throw new RuntimeException("ffmpeg执行异常" + e.getMessage());
        }
        return cmdResult;
    }

    /**
     * 将秒表示时长转为00:00:00格式
     *
     * @param millisecond 毫秒数时长
     * @return 字符串格式时长
     */
    private static String parseTimeToString(long millisecond) {
        long second = millisecond/1000;
        if (second==0){
            return "00:00:00";
        }
        long end = second % 60;
        long mid = second / 60;
        if (mid < 60) {
            return "00:"+mid + ":" + end;
        } else if (mid == 60) {
            return "01:00:" + end;
        } else {
            long first = mid / 60;
            mid = mid % 60;
            String s = "";
            if (first>9){
                s = first + ":" + mid + ":" + end;
            }else{
                s = "0"+first + ":" + mid + ":" + end;
            }
            return s;
        }

    }
}
